import { bus } from "@/bus";
import { loadConfig } from '@/config.ts'
import { decode } from "@msgpack/msgpack"
import * as crypto from 'crypto'
import { DataSource } from "typeorm";
let conf: any = null
let decipher: crypto.Cipher | null = null
let key: Buffer | null = null
let iv: Buffer | null = null
let key_sh: Buffer;
let iv_sh: Buffer;
// 解析 网关/msgpack
export async function setup() {

    conf = await loadConfig();

    key = Buffer.from(conf.default.report.crypto.key, "hex");
    iv = Buffer.from(conf.default.report.crypto.iv, "hex");
    key_sh = Buffer.from(conf.default.report.crypto_sh.key, "hex");
    iv_sh = Buffer.from(conf.default.report.crypto_sh.iv, "hex");

    bus.on('wb.adv.received:msgpack', (message: Buffer) => {
        let fields = decode(message) as any[];
        let formatVersion = fields[0] as number;
        if (gwPackParsers[formatVersion]) {
            try {
                let pack = gwPackParsers[formatVersion](fields);
                bus.emit('wb.adv.decode', pack);
            } catch (e) {
                console.error(`解析数据包失败: ${e}`);
            }
        } else {
            return;
        }
    });

    bus.on('wb.adv.received', async (message: Buffer) => {
        let fields = JSON.parse(message.toString());
        if (fields.action === 'adv') {
            let formatVersion = 0;
            if (gwPackParsers[formatVersion]) {
                try {
                    let pack = await gwPackParsers[formatVersion](fields);
                    bus.emit('wb.adv.decode', pack);
                } catch (e) {
                    console.error(`解析数据包失败: ${e}`);
                }
            } else {
                return;
            }
        }
    });
}


function binToMac(bufMac: Buffer) {
    let mac = ''
    for (let i = 0; i < 6; i++) {
        mac += bufMac[i].toString(16).padStart(2, '0')
        if (i < 5) {
            mac += ':'
        }
    }
    return mac
}

// 网关数据包解析器
const gwPackParsers: { [key: number]: (feilds: any[]) => void } = {
    // 格式版本 0
    0: async function (feilds: any) {
        let { gw, wb } = feilds
        let pack: any = {
            mac: feilds.gw.gw_mac,
            ip: '0.0.0.0',
            frm_ver: `${gw.version_bin}/${gw.version_fs}`,
            // id: liveSec,
            // live_sec: liveSec,
            wb_adv: []
        }
        for (let item of wb) {
            let dataFormat = item.format
            if (wbPackParsers[dataFormat]) {
                try {
                    let wbpack: any = await wbPackParsers[dataFormat](Buffer.from(item.data, 'base64'))
                    // console.log('0000', wbpack)
                    wbpack.mac = gw.gw_mac
                    wbpack.rssi = item.rssi
                    wbpack.firmware_ver = gw.version_fs
                    wbpack.format_ver = item.format
                    pack.wb_adv.push(wbpack)
                } catch (e) {
                    console.error(`解析数据包失败: ${e}`)
                }
            } else { }
        }
        // console.log('pack', pack)
        return pack
    },
    // 格式版本 1
    1: function (feilds: any[]) {
        let [, liveSec, bufGwMac, frmVer, bufIp, arrData] = feilds
        let gwMac = binToMac(bufGwMac)

        let ip = ''
        for (let i = 0; i < 4; i++) {
            ip += bufIp[i].toString(10)
            if (i < 3) {
                ip += '.'
            }
        }

        let pack: any = {
            mac: gwMac,
            ip: ip,
            frm_ver: frmVer,
            id: liveSec,
            live_sec: liveSec,
            wb_adv: []
        }

        for (let [buWbMac, rssi, raw] of arrData) {
            let dataFormat = raw[1]
            // console.log('format', raw[1])
            if (wbPackParsers[dataFormat]) {
                try {
                    let wbpack: any = wbPackParsers[dataFormat](raw)
                    wbpack.mac = binToMac(buWbMac)
                    wbpack.rssi = rssi
                    pack.wb_adv.push(wbpack)
                } catch (e) {
                    console.error(`解析数据包失败: ${e}`)
                }
            } else {
                // console.error(`不支持的格式版本: ${dataFormat}`)
            }
        }

        return pack
    }
}

// 手环数据包解析器
const wbPackParsers: { [key: number]: (raw: Buffer) => void } = {
    // // 格式版本 0 (有问题)
    // 0: async function (raw: Buffer) {
    //     console.log('format 0', raw)
    //     let decryptedBuffer = await decrypt(raw.slice(4))
    //     // console.log('decryptedData',  new Uint8Array(decryptedBuffer))
    //     let decryptedData = new Uint8Array(decryptedBuffer)
    //     return {
    //         steps: (decryptedData[0] << 8) | decryptedData[1], // 步数
    //         hr: decryptedData[2], // 心跳
    //         acc_x: (decryptedData[3] << 8) | decryptedData[4], // x 轴
    //         acc_y: (decryptedData[5] << 8) | decryptedData[6], // y 轴
    //         acc_z: (decryptedData[7] << 8) | decryptedData[8], // z 轴
    //         temp: (decryptedData[9] << 8 | (decryptedData[10])) / 100, // 体温
    //         hrv: (decryptedData[11] << 8) | decryptedData[12], // HRV
    //         beacon1: (decryptedData[13] << 8) | decryptedData[14], // iBeacon ID1
    //         beacon2: (decryptedData[15] << 8) | decryptedData[16], // iBeacon ID2
    //         beacon3: (decryptedData[17] << 8) | decryptedData[18], // iBeacon ID3
    //         charging: !!(decryptedData[19] & 0x01) ? 1 : 0, // 检查最低位（第0位）充电状态
    //         wear_on: !!(decryptedData[19] & 0x02) ? 1 : 0, // 检查第1位 佩戴状态
    //         req_rt: !!(decryptedData[19] & 0x04) ? 1 : 0, // 检查第2位 是否授时
    //         fake_hr: !!(decryptedData[19] & 0x08) ? 1 : 0, // 检查第3位 是否伪造心率
    //         bat_vol: decryptedData[20], // 电池电量
    //     }
    // },
    // 格式版本 1
    1: async function (raw: Buffer) {
        // console.log('format 1', raw)
        let decryptedData = await decrypt0(raw.slice(4))
        let beaconNumber =
            (decryptedData[3] << 24) + (decryptedData[2] << 16) + (decryptedData[1] << 8) + decryptedData[0];
        return {
            idx: decryptedData[19],
            beacon1: beaconNumber & 0x1ff,
            beacon2: (beaconNumber >> 9) & 0x1ff,
            beacon3: (beaconNumber >> 18) & 0x1ff,
            acc_x: decryptedData[4] + (decryptedData[5] << 8),
            acc_y: decryptedData[6] + (decryptedData[7] << 8),
            acc_z: decryptedData[8] + (decryptedData[9] << 8),
            steps: decryptedData[10] + (decryptedData[11] << 8),
            hrv: decryptedData[12] + (decryptedData[13] << 8),
            hr: decryptedData[14],
            hr_confidence: decryptedData[15],
            temp: (decryptedData[16] * 2) / 10, // 0 表示充电
            bat_vol: decryptedData[17],
            charging: !!(decryptedData[18] & 0x01) ? 1 : 0,
            wear_on: !!(decryptedData[18] & 0x02) ? 1 : 0,
            req_rt: !!(decryptedData[18] & 0x04) ? 1 : 0,
            fake_hr: !!(decryptedData[18] & 0x08) ? 1 : 0,
        }
    },
    // 格式版本 2
    2: function (raw: Buffer) {
        let decryptedData = decrypt(raw.slice(5))
        let intBeacon = decryptedData.readUint32LE(0)
        return {
            firmware_ver: raw[0],
            format_ver: raw[1],
            idx: raw[2],
            charging: !!(raw[3] & 0x01) ? 1 : 0,
            wear_on: !!(raw[3] & 0x02) ? 1 : 0,
            req_rt: !!(raw[3] & 0x04) ? 1 : 0,
            fake_hr: !!(raw[3] & 0x08) ? 1 : 0,
            bat_vol: raw[4],
            beacon1: intBeacon & 0x1ff,
            beacon2: (intBeacon >> 9) & 0x1ff,
            beacon3: (intBeacon >> 18) & 0x1ff,
            motion: decryptedData.readFloatLE(4),
            motion_variance: decryptedData.readFloatLE(8),
            steps: decryptedData.readUint16LE(12),
            hrv: decryptedData.readUint16LE(14),
            hr: decryptedData.readUint8(16),
            hr_confidence: decryptedData.readUint8(17),
            temp: decryptedData.readUint8(18) * 2 / 10,
        }
    },
    // // 格式版本 16
    // 16: function (raw: Buffer) {
    //     let decryptedData = decrypt(raw.slice(4))
    //     console.log('format 16', decryptedData)
    // }

}

// 解密函数
function decrypt(encryptedBuffer: Buffer) {
    // if (!decipher) {
    // Fallback to create decipher if not already initialized
    decipher = crypto.createDecipheriv('aes-128-ctr', key as any, iv as any)
    // }

    // Need to reset the decipher state for each new buffer
    decipher.setAutoPadding(true)
    return Buffer.concat([decipher.update(encryptedBuffer), decipher.final()])
}

function test_decrypt() {
    let decrypted = Buffer.from([0x83, 0xdd, 0x7c, 0xed, 0x09, 0x8b, 0x7e, 0x47, 0x1d, 0x8e, 0x87, 0xf0, 0x90, 0x60, 0x07, 0xa2, 0xd4, 0xee])
    console.log(decrypt(decrypted))

    let plaintxt = Buffer.from([0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14])
    console.log(plaintxt)
}



// 解密
async function decrypt0(ciphertext: any) {
    const decipher = crypto.createDecipheriv('aes-128-ctr', key_sh, iv_sh);
    let decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
    return decrypted;
}